--- @param extension Package
--- @param HY HY_Utility
--- @param U Utility
return function(extension, HY, U)
    local desc_flag = [[
        ## 规则简介

    游戏开始时，随机一名角色获得“旗”，该角色成为最后一名行动的角色，有“旗”的角色成为伤害类牌的目标后或受到1点伤害后摸一张牌。

    其他角色对有“旗”的角色造成伤害后，可以尝试夺旗（选择一项：1.进行判定，结果为♠则夺旗；2.弃置两张同色手牌并夺旗。）

    有“旗”的角色死亡后，若有存活的击杀者，击杀者自动夺旗；否则随机一名存活角色获得“旗”。

    每轮结束时，所有死亡角色复活并摸四张牌。

    ---

    ## 胜利条件

    第一名获得30积分的玩家获得胜利。

        ---

    ## 积分规则

  一轮结束时持有“旗”——计6分

  对有“旗”的角色造成伤害——每点伤害计2分

  成功夺旗——计3分
]]

    local flag_mode = fk.CreateGameMode {
        name = "flag_mode",
        minPlayer = 3,
        maxPlayer = 8,
        logic = function()
            local flag_logic = GameLogic:subclass("flag_logic")

            function flag_logic:assignRoles()
                local room = self.room
                local n = #room.players

                for i = 1, n do
                    local p = room.players[i]
                    p.role = "hidden"
                    room:setPlayerProperty(p, "role_shown", true)
                    room:broadcastProperty(p, "role")
                end

                self.start_role = "hidden"
                -- for adjustSeats
                room.players[1].role = "lord"
            end

            function flag_logic:chooseGenerals()
                local room = self.room
                local generalNum = room:getSettings('generalNum')
                local n = room:getSettings('enableDeputy') and 2 or 1
                local lord = room:getLord()
                if not lord then
                    local temp = room.players[1]
                    temp.role = "lord"
                    lord = temp
                end
                room:setCurrent(lord)
                lord.role = self.start_role

                local players = room.players
                local generals = room:getNGenerals(#players * generalNum)
                local req = Request:new(players, "AskForGeneral")
                table.shuffle(generals)
                for i, p in ipairs(players) do
                    local arg = table.slice(generals, (i - 1) * generalNum + 1, i * generalNum + 1)
                    req:setData(p, { arg, n })
                    req:setDefaultReply(p, table.random(arg, n))
                end

                req:ask()

                local selected = {}
                for _, p in ipairs(players) do
                    local gs = req:getResult(p)
                    local general = gs[1]
                    local deputy = gs[2]
                    room:setPlayerGeneral(p, general, true, true)
                    room:setDeputyGeneral(p, deputy)
                end
                generals = table.filter(generals, function(g) return not table.contains(selected, g) end)
                room:returnToGeneralPile(generals)

                room:askToChooseKingdom(players)
            end

            return flag_logic
        end,
        rule = "#flag_rule",
        winner_getter = function(self, victim)
            local room = Fk:currentRoom()
            for _, t in ipairs(room.players) do
                if room:getBanner("flag_score")[t] >= 30 then
                    t.role = "renegade"
                    return "renegade"
                end
            end
            return ""
        end,
    }

    ---@param room Room
    ---@param player ServerPlayer
    local function SetFlag(room, player)
        for _, t in ipairs(room.players) do
            t.tag["flag"] = false
            room:setPlayerMark(t, "@@flag_mark", 0)
        end
        player.tag["flag"] = true
        room:setPlayerMark(player, "@@flag_mark", 1)
    end
    ---@param room Room
    ---@return ServerPlayer|nil
    local function FlagPlayer(room)
        local flag = table.filter(room.players, function(t)
            return t.tag["flag"]
        end)
        if #flag == 1 then
            return flag[1]
        end
        return nil
    end
    ---@param room Room
    ---@param player ServerPlayer
    ---@param num integer
    local function AddScore(room, player, num)
        local scores = room:getBanner("flag_score") or {}
        scores[player] = (scores[player] or 0) + num
        room:setBanner("flag_score", scores)
        room:setPlayerMark(player, "@flag_score", scores[player])
        local winner = Fk.game_modes[room:getSettings('gameMode')]:getWinner(nil)
        if winner ~= "" then
            room:doBroadcastNotify("ShowToast", player.serverplayer:getScreenName() .. Fk:translate("flag_result"))
            room:delay(2000)
            room:gameOver(winner)
        end
    end
    local flag_rule = fk.CreateSkill {
        name = "#flag_rule",
    }
    flag_rule:addEffect(fk.RoundEnd, {
        priority = 0.001,
        can_refresh = Util.TrueFunc,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            local deadPlayers = table.filter(room.players, function(t)
                return t.dead
            end)
            if #deadPlayers > 0 then
                table.sort(deadPlayers, function(a, b)
                    return a.seat > b.seat
                end)
                for _, t in ipairs(deadPlayers) do
                    room:revivePlayer(t, false)
                    room:drawCards(t, 4)
                    AddScore(room, t, 0)
                end
            end
            local flagPlayer = FlagPlayer(room)
            if flagPlayer and player == flagPlayer then
                AddScore(room, flagPlayer, 6)
            end
        end
    })
    flag_rule:addEffect(fk.GameStart, {
        priority = 0.001,
        can_refresh = Util.TrueFunc,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            if player.seat == #room.players then
                SetFlag(room, player)
            end
            local scores = room:getBanner("flag_score") or {}
            scores[player] = 0
            room:setBanner("flag_score", scores)
            room:setTag("SkipNormalDeathProcess", true)
            room:setTag("SkipGameRule", true)
        end
    })
    flag_rule:addEffect(fk.Deathed, {
        priority = 0.001,
        can_refresh = function(self, event, target, player, data)
            return target == player and player.tag["flag"]
        end,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            if data.damage and data.damage.from and data.damage.from ~= player then
                SetFlag(room, data.damage.from)
                AddScore(room, data.damage.from, 3)
            else
                SetFlag(room, table.random(room.alive_players))
            end
            local winner = Fk.game_modes[room:getSettings('gameMode')]:getWinner(player)
            if winner ~= "" then
                room:gameOver(winner)
                return true
            end
        end
    })
    flag_rule:addEffect(fk.GameOverJudge, {
        priority = 0.001,
        can_refresh = Util.TrueFunc,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            room:setTag("SkipGameRule", true)
        end
    })
    flag_rule:addEffect(fk.TargetConfirmed, {
        priority = 0.001,
        can_refresh = function(self, event, target, player, data)
            return player.tag["flag"] and target == player and data.card and data.card.is_damage_card
        end,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            room:drawCards(player, 1)
        end
    })
    flag_rule:addEffect(fk.Damaged, {
        priority = 0.001,
        can_refresh = function(self, event, target, player, data)
            return player.tag["flag"] and target == player
        end,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            room:drawCards(player, data.damage)
        end
    })
    flag_rule:addEffect(fk.Damage, {
        priority = 0.001,
        can_refresh = function(self, event, target, player, data)
            return target == player and not player.tag["flag"] and data.to and data.to.tag["flag"]
        end,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            AddScore(room, player, data.damage * 2)
            ::AskForFlagPrey::
            local choices = { "flag_prey_judge", "flag_prey_discard", "Cancel" }
            local result = room:askToChoice(player, {
                choices = choices,
                skill_name = "flag_prey",
                prompt = "flag_prey_prompt"
            })
            if result == "flag_prey_judge" then
                local judge = {
                    who = player,
                    reason = "flag_prey",
                    pattern = ".|.|spade"
                }
                room:judge(judge)
                if judge.card.suit == Card.Spade then
                    SetFlag(room, player)
                    AddScore(room, player, 3)
                end
            elseif result == "flag_prey_discard" then
                local _, use = room:askToUseActiveSkill(player, {
                    skill_name = "flag_prey_active",
                    prompt = "flag_prey_active_prompt",
                })
                if use then
                    room:throwCard(use.cards, "flag_prey", player, player)
                    SetFlag(room, player)
                    AddScore(room, player, 3)
                else
                    goto AskForFlagPrey
                end
            end
        end
    })
    local flag_prey_active = fk.CreateSkill {
        name = "flag_prey_active",
    }
    flag_prey_active:addEffect("active", {
        card_num = 2,
        card_filter = function(self, player, to_select, selected)
            if #selected == 0 then
                return table.contains(player.player_cards[Player.Hand], to_select)
            elseif #selected == 1 then
                return Fk:getCardById(to_select).color == Fk:getCardById(selected[1]).color and
                    table.contains(player.player_cards[Player.Hand], to_select)
            end
        end,
    })

    extension:loadSkillSkels { flag_rule, flag_prey_active }
    extension:addGameMode(flag_mode)

    Fk:loadTranslationTable {
        ["flag_mode"] = "夺旗模式",
        [":flag_mode"] = desc_flag,
        ["@@flag_mark"] = "旗",
        ["@flag_score"] = "积分",
        ["flag_prey"] = "夺旗",
        ["flag_prey_active"] = "夺旗",
        ["flag_prey_prompt"] = "选择一种夺旗方式",
        ["flag_prey_judge"] = "判定",
        ["flag_prey_discard"] = "弃牌",
        ["flag_prey_active_prompt"] = "弃置两张同色手牌",
        ["flag_result"] = "率先到达了30分，游戏结束！",
    }
end
